#pragma once
#include <iostream>
#include <cpp-httplib/httplib.h>
#include "protos/add_contact.pb.h"
#include "protos/del_contact.pb.h"
#include "protos/view_contact_list.pb.h"
#include "protos/view_contact.pb.h"
#include "contacts_exception.hh"

void buildAddContactRequest(add_contact::AddContactRequest *req) // 由用户输入，构造新增联系人
{
    std::cout << "----------添加新联系人----------" << std::endl;
    // 输入姓名
    std::cout << "请输入姓名: ";
    std::string name;
    std::getline(std::cin, name);
    req->set_name(name);

    // 输入年龄
    std::cout << "请输入年龄: ";
    int age;
    std::cin >> age;
    req->set_age(age);
    std::cin.ignore(256, '\n');

    // 输入电话
    while (1)
    {
        // 1.设置电话号码
        std::cout << "请输入电话号码(回车结束): ";
        std::string phone_number;
        std::getline(std::cin, phone_number);
        if (phone_number.empty())
            break;

        auto *phone = req->add_phone();
        phone->set_number(phone_number);

        // 2.设置电话类型
        std::cout << "请选择电话类型(0.移动 1.固定): ";
        int type;
        std::cin >> type;
        std::cin.ignore(256, '\n');
        switch (type)
        {
        case 0:
            phone->set_type(add_contact::AddContactRequest_Phone_PhoneType::AddContactRequest_Phone_PhoneType_MOB);
            break;
        case 1:
            phone->set_type(add_contact::AddContactRequest_Phone_PhoneType::AddContactRequest_Phone_PhoneType_TEL);
            break;
        default:
            std::cout << "非法类型，使用默认值" << std::endl;
            break;
        }
    }

    std::cout << "----------新联系人已创建---------" << std::endl;
}

void addContact(httplib::Client &client)
{
    // 1.构造一个联系人添加请求
    add_contact::AddContactRequest add_req;
    buildAddContactRequest(&add_req);

    // 2.序列化add请求
    std::string add_req_str;
    if (!add_req.SerializeToString(&add_req_str))
        throw ContactException("Fail to serialze AddContactRequest"); // 序列化失败，直接抛异常

    // 3.向服务器发送post add请求
    auto res = client.Post("/contacts/add", add_req_str, "application/protobuf");

    // 4.对响应结果进行分析（错误排查）
    if (!res)
    {
        // 没有收到服务器的响应
        std::string err_desc("post /contacts/add 连接错误，异常信息：");
        err_desc += httplib::to_string(res.error());
        throw ContactException(err_desc);
    }

    if (res->status != 200)
    {
        // 服务端处理异常
        std::string err_desc("post /contacts/add 服务处理错误，错误原因：");
        err_desc += res->reason; // 状态描述（错误原因）
        throw ContactException(err_desc);
    }

    add_contact::AddContactResponse add_resp;
    if (!add_resp.ParseFromString(res->body)) // 反序列化出add响应
    {
        // 反序列化失败
        throw ContactException("Fail to parse AddContactResponse");
    }

    if (!add_resp.base_resp().success())
    {
        // 服务端处理结果异常
        std::string err_desc("post /contacts/add 服务结果异常，异常信息：");
        err_desc += add_resp.base_resp().err_desc();
        throw ContactException(err_desc);
    }

    // 5.add响应合法，输出联系人uid，告知用户添加成功
    std::cout << "联系人id: " << add_resp.uid() << " 添加成功！" << std::endl;
}

void deleteContact(httplib::Client &client)
{
    // 1.构造一个删除联系人请求
    del_contact::DelContactRequest del_req;

    std::cout << "输入删除联系人的ID: ";
    std::string uid;
    std::getline(std::cin, uid);

    del_req.set_uid(uid);

    // 2.序列化delete请求
    std::string del_req_str;
    if (!del_req.SerializeToString(&del_req_str))
        throw ContactException("Fail to serialze DelContactRequest");

    // 3.向服务端发送post delete请求
    auto res = client.Post("/contacts/delete", del_req_str, "application/protobuf");
    if (!res)
    {
        std::string err_desc("post /contacts/delete 连接错误，异常信息：");
        err_desc += httplib::to_string(res.error());
        throw ContactException(err_desc);
    }

    // 4.反序列化delete响应
    del_contact::DelContactResponse del_resp;
    if (!del_resp.ParseFromString(res->body))
        throw ContactException("Fail to parse DelContactRequest");

    if (res->status != 200)
    {
        // 服务端处理失败
        std::string err_desc("post /contacts/delete 服务处理错误，错误原因：");
        err_desc += res->reason; // 状态描述（错误原因）
        throw ContactException(err_desc);
    }
    if (!del_resp.base_resp().success())
    {
        // 服务端处理结果异常
        std::string err_desc("post /contacts/delete 服务结果异常，异常信息：");
        err_desc += del_resp.base_resp().err_desc();
        throw ContactException(err_desc);
    }

    // 5.删除成功
    std::cout << "联系人id: " << del_resp.uid() << " 已删除" << std::endl;
}

void viewContactList(httplib::Client &client)
{
    // 1.发送获取通讯录列表请求
    auto res = client.Get("/contacts/list");

    if (!res)
    {
        std::string err_desc("get /contacts/list 服务结果异常，异常信息：");
        err_desc += httplib::to_string(res.error());
        throw ContactException(err_desc);
    }

    view_contact_list::ViewContactListResponse view_list_resp;
    if (!view_list_resp.ParseFromString(res->body))
        throw ContactException("Fail to parse ViewContactListResponse");

    if (res->status != 200)
    {
        // 服务端处理失败
        std::string err_desc("get /contacts/list 服务处理错误，错误原因：");
        err_desc += res->reason; // 状态描述（错误原因）
        throw ContactException(err_desc);
    }

    if (!view_list_resp.base_resp().success())
    {
        // 服务端处理结果异常
        std::string err_desc("get /contacts/list 服务结果异常，异常信息：");
        err_desc += view_list_resp.base_resp().err_desc();
        throw ContactException(err_desc);
    }

    // 获取联系人列表成功, 输出
    for (int i = 0; i < view_list_resp.contacts_size(); i++)
    {
        view_contact_list::PeopleInfo contact = view_list_resp.contacts(i);
        std::cout << "-------------联系人" << i + 1 << "-------------" << std::endl;
        std::cout << "id:" << contact.uid() << "\t"
                  << "name: " << contact.name() << std::endl << std::endl;
    }
}

void viewContact(httplib::Client &client)
{
    // 1.通过用户输入，获取联系人uid
    std::cout << "输入查询联系人的ID: ";
    std::string uid;
    std::getline(std::cin, uid);

    // 2.发送get请求，uid在url中
    const std::string url = "/contacts/list/" + uid;
    auto res = client.Get(url);

    if (!res)
    {
        std::string err_desc = "get " + url;
        err_desc += " 服务结果异常，异常信息：";
        err_desc += httplib::to_string(res.error());
        throw ContactException(err_desc);
    }

    // 3.反序列化接收到的响应
    view_contact::ViewContactResponse view_one_resp;
    if (!view_one_resp.ParseFromString(res->body))
        throw ContactException("Fail to parse ViewContactResponse");

    if (res->status != 200)
    {
        // 服务端处理失败
        std::string err_desc = "get " + url;
        err_desc += " 服务处理错误，错误原因：";
        err_desc += res->reason; // 状态描述（错误原因）
        throw ContactException(err_desc);
    }

    if (!view_one_resp.base_resp().success())
    {
        // 服务端处理结果异常
        std::string err_desc = "get " + url;
        err_desc += " 服务结果异常，异常信息：";
        err_desc += view_one_resp.base_resp().err_desc();
        throw ContactException(err_desc);
    }

    // 4.获取联系人成功，输出
    std::cout << "----------联系人--------" << std::endl;
    std::cout << "姓名: " << view_one_resp.name() << std::endl;
    std::cout << "年龄: " << view_one_resp.age() << std::endl;

    for (int i = 0; i < view_one_resp.phone_size(); i++)
    {
        auto phone = view_one_resp.phone(i);
        if (phone.type() == view_contact::ViewContactResponse_Phone_PhoneType::ViewContactResponse_Phone_PhoneType_MOB)
            std::cout << "电话" << i+1 << ": " << phone.number() << " (移动电话)" << std::endl;
        else
            std::cout << "电话" << i+1 << ": " << phone.number() << " (固定电话)" << std::endl;
    }
}